package Store

//https://docs.hypermode.com/badger/quickstart
import (
	"errors"
	"fmt"
	"github.com/dgraph-io/badger/v4"
	"db2s/ref"
	"os"
	"strings"
)

type BadgerDb struct {
	DataDir string //数据目录路径
	dbFile  map[string]*badger.DB
}

func (bg BadgerDb) getBadgerDb(query string) *badger.DB {
	for k, v := range bg.dbFile {
		if strings.HasSuffix(k, query) {
			return v
		}
	}
	return nil
}
func (bg BadgerDb) Create() {

}
func (bg BadgerDb) Drop(table string) (err error) {
	dir := bg.getBadgerDb(table).Opts().Dir
	if err = bg.getBadgerDb(table).Close(); err != nil {
		return
	}
	err = os.RemoveAll(dir)
	return
}
func (bg *BadgerDb) Open(f ...string) (err error) {
	var db *badger.DB
	for _, dbFile := range f {
		dbFile = fmt.Sprintf("%v/%v", bg.DataDir, dbFile)
		options := badger.DefaultOptions(dbFile).WithSyncWrites(true).WithLoggingLevel(badger.ERROR)
		if db, err = badger.Open(options); err != nil {
			return fmt.Errorf("failed to open database %s: %w", dbFile, err)
		}
		bg.dbFile[dbFile] = db
	}
	return
}
func (bg BadgerDb) Close() (err error) {
	for _, db := range bg.dbFile {
		if closeErr := db.Close(); closeErr != nil {
			return
			// 记录关闭错误但不影响主流程
			// 可以考虑使用日志记录closeErr
		}
	}
	return
}
func (bg BadgerDb) queryAll(table string) (result map[string]string, err error) {
	result = make(map[string]string)
	err = bg.getBadgerDb(table).View(func(txn *badger.Txn) error {
		opts := badger.DefaultIteratorOptions
		opts.PrefetchSize = 10
		it := txn.NewIterator(opts)
		defer it.Close()
		for it.Rewind(); it.Valid(); it.Next() {
			item := it.Item()
			k := item.Key()
			err = item.Value(func(v []byte) error {
				result[string(k)] = string(v)
				return nil
			})
			if err != nil {
				return err
			}
		}
		return nil
	})
	return
}
func (bg BadgerDb) QueryKey(table string, key string) (result map[string]string, err error) {
	var valCopy []byte
	result = make(map[string]string)
	err = bg.getBadgerDb(table).View(func(txn *badger.Txn) error {
		var item *badger.Item
		if item, err = txn.Get([]byte(key)); err != nil {
			return err
		}
		valCopy, err = item.ValueCopy(nil)
		return nil
	})
	if len(valCopy) == 0 {
		return
	}
	result[key] = string(valCopy)
	return
}
func (bg BadgerDb) Query(table string, key string) (result map[string]string, err error) {
	result = make(map[string]string)
	switch key {
	case "all":
		return bg.queryAll(table)
	default:
		result, err = bg.QueryKey(table, key)
		if err != nil {
			// 假设 badger 提供了特定的错误类型，如 badger.ErrKeyNotFound
			// 如果没有，则需要根据实际的错误类型调整
			if strings.Contains(err.Error(), "Key not found") {
				// 确保即使键不存在也返回一个空 map 而不是 nil
				return result, nil
			}
			return
		}
	}
	return
}
func (bg BadgerDb) Insert(query string, updates map[string]string) (err error) {
	return bg.Update(query, updates)
}
func (bg BadgerDb) Update(query string, updates map[string]string) (err error) {
	txn := bg.getBadgerDb(query).NewTransaction(true)
	for k, v := range updates {
		if err = txn.Set([]byte(k), []byte(v)); errors.Is(err, badger.ErrTxnTooBig) {
			err = txn.Commit()
			txn = bg.getBadgerDb(query).NewTransaction(true)
			err = txn.Set([]byte(k), []byte(v))
		}
	}
	err = txn.Commit()
	return
}
func (bg BadgerDb) Delete() {

}
func (bg BadgerDb) Truncate(query string) (err error) {
	return bg.getBadgerDb(query).DropAll()
}
func (bg BadgerDb) Sync(query string) (err error) {
	return bg.getBadgerDb(query).Sync()
}
func (bg BadgerDb) MetaData() {

}
func (bg *BadgerDb) Init() {
	bg.dbFile = make(map[string]*badger.DB)
}
func (bg BadgerDb) BaseDirInitStorage() (err error) {
	//存储目录判断
	if bg.DataDir == "" {
		return
	}
	if _, err = ref.ReconPath(bg.DataDir); err != nil {
		return fmt.Errorf("failed to reconstruct path %s: %w", bg.DataDir, err)
	}
	return
}
